package com.ants.boot.utils.pdf;

import com.alibaba.fastjson.JSONObject;
import com.ants.boot.utils.pdf.exception.PdfExportException;
import com.itextpdf.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Locale;
import java.util.Map;

/**
 * @author 蚂蚁会花呗
 * @create 2025/3/4 15:23
 * 生成pdf文档的工具类
 */
public class PdfUtils {

    private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class);

    /**
     * 初始化freemarker
     */
    private static Configuration configuration = null;
    static {
        configuration = new Configuration();
        configuration.setEncoding(Locale.getDefault(), "utf-8");
    }

    /**
     * 加载模板，填充参数后导出html模板
     * @param templatePath
     * @param variables
     */
    public static void readTemplateAndExportHtml(TemplatePathOfPdf templatePath, Map<String, Object> variables){
        try{
            configuration.setDirectoryForTemplateLoading(new File(templatePath.getTemplatePath()));
            Template template = configuration.getTemplate(templatePath.getTemplateName());
            File html = new File( templatePath.getHtmlPath() + templatePath.getHtmlName());
            FileOutputStream fileOutputStream = new FileOutputStream(html);
            template.process(variables, new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8));
            fileOutputStream.flush();
            fileOutputStream.close();
        }catch (Exception e){
            logger.error("加载模板并填充参数失败");
            e.printStackTrace();
        }
    }

    /**
     * 根据模板导出pdf
     * @param templatePath 模板
     *                     htmlPath、htmlName可以和pdfPath、pdfName 一样，如果一样最终只生成pdf文档，如果不一样会另外生成一个html
     *                     最终是通过填充后的html转换成pdf的
     * @param variables  参数
     */
    public static void exportPdf(TemplatePathOfPdf templatePath,Map<String, Object> variables){
        try{
            //校验必填参数
            validParam(templatePath);
            //读取模板
            readTemplateAndExportHtml(templatePath,variables);

            //加载html模板
            String htmlUrl = new File(templatePath.getHtmlPath() + templatePath.getHtmlName()).toURI().toURL().toString();
            ITextRenderer iTextRenderer = new ITextRenderer();
            iTextRenderer.setDocument(htmlUrl);
            //字体
            ITextFontResolver iTextFontResolver = iTextRenderer.getFontResolver();
            iTextFontResolver.addFont(templatePath.getFontPath() + templatePath.getFontName(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            //解决图片相对路径问题
            iTextRenderer.getSharedContext().setBaseURL("file://" + templatePath.getPicturePath());

            //生成PDF
            String pdfUrl = templatePath.getPdfPath() + templatePath.getPdfName();
            OutputStream outputStream = Files.newOutputStream(Paths.get(pdfUrl));
            iTextRenderer.layout();
            iTextRenderer.createPDF(outputStream);
            outputStream.flush();
            outputStream.close();
            logger.debug("pdf报告生成完成：" + pdfUrl);

        }catch (Exception e){
            logger.error("pdf报告生成失败：" + e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * 校验参数
     * @return
     */
    public static void validParam(TemplatePathOfPdf templatePath){
        if (StringUtils.isBlank(templatePath.getTemplatePath()) && StringUtils.isBlank(templatePath.getTemplateName())){
            logger.error("模板的路径和名称不能为空");
            throw new PdfExportException("模板的路径和名称不能为空");
        }
        if (StringUtils.isBlank(templatePath.getHtmlPath()) && StringUtils.isBlank(templatePath.getHtmlName())){
            logger.error("填充后的模板不能为空");
            throw new PdfExportException("填充后的模板不能为空");
        }
        if (StringUtils.isBlank(templatePath.getFontPath()) && StringUtils.isBlank(templatePath.getFontName())){
            logger.error("字体的路径和名称不能为空");
            throw new PdfExportException("字体的路径和名称不能为空");
        }
        if (StringUtils.isBlank(templatePath.getPdfPath()) && StringUtils.isBlank(templatePath.getPdfName())){
            logger.error("导出的路径和名称不能为空");
            throw new PdfExportException("导出的路径和名称不能为空");
        }
    }

/*    public static void main(String[] args) {
        TemplatePathOfPdf  templatePathOfPdf = new TemplatePathOfPdf();
        templatePathOfPdf.setTemplatePath("D://tmp//test//template//");
        templatePathOfPdf.setTemplateName("assessmentReportTemplate.html");
        templatePathOfPdf.setHtmlPath("D://tmp//test//html//");
        templatePathOfPdf.setHtmlName("test.html");
        templatePathOfPdf.setFontPath("D://tmp//test//template//");
        templatePathOfPdf.setFontName("simsun.ttf");
        templatePathOfPdf.setPdfPath("D://tmp//test//pdf//");
        templatePathOfPdf.setPdfName("test.pdf");
        templatePathOfPdf.setPicturePath("D://tmp//test//template//");
        String jsonStr = "{\"disease\":\"外周动脉疾病\",\"dmdzdbdgc\":\"\",\"jbxiNl\":\"70\",\"jbxiSfzh\":\"330124195103173728\",\"jbxiXb\":\"女\",\"jbxiXm\":\"杨月兰\",\"name\":\"十年心血管病风险评估为超高危\",\"pdfBgrq\":\"2025-03-03 17:18:09\",\"suggest\":\"保持情绪稳定，避免情绪激动导致血压升高。同时，控制饮食，避免暴饮暴食，以免加重心脏负担。注重休息，进行适量的体育锻炼，并控制体重、血压、血糖和血脂等，以降低心血管疾病复发风险,可在医生指导下使用药物\\n您的BMI为22.04, 正常\",\"tgjcBmi\":\"22.04\",\"tgjcBmiZh\":\"正常\",\"tgjcHeight\":\"165\",\"tgjcWaistline\":\"32\",\"tgjcWeight\":\"60\",\"type\":\"LDL-C≥4.9mmol/L、高血压\",\"typeName\":\"ASCVD\"}";
        Map<String,Object> map = JSONObject.parseObject(jsonStr,Map.class);
        exportPdf(templatePathOfPdf, map);
//        readTemplateAndExportHtml(templatePathOfPdf, map);

    }*/

    public static void main(String[] args) {
        logger.info("This is a debug message");
    }

}
